home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Mail / pine3.92 / pine / ttyout.c < prev   
C/C++ Source or Header  |  1996-03-14  |  55KB  |  2,150 lines

  1. #if !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: ttyout.c,v 4.71 1996/03/15 07:13:42 hubert Exp $";
  3. #endif
  4. /*----------------------------------------------------------------------
  5.  
  6.             T H E    P I N E    M A I L   S Y S T E M
  7.  
  8.    Laurence Lundblade and Mike Seibel
  9.    Networks and Distributed Computing
  10.    Computing and Communications
  11.    University of Washington
  12.    Administration Builiding, AG-44
  13.    Seattle, Washington, 98195, USA
  14.    Internet: lgl@CAC.Washington.EDU
  15.              mikes@CAC.Washington.EDU
  16.  
  17.    Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  18.  
  19.  
  20.    Pine and Pico are registered trademarks of the University of Washington.
  21.    No commercial use of these trademarks may be made without prior written
  22.    permission of the University of Washington.
  23.  
  24.    Pine, Pico, and Pilot software and its included text are Copyright
  25.    1989-1996 by the University of Washington.
  26.  
  27.    The full text of our legal notices is contained in the file called
  28.    CPYRIGHT, included with this distribution.
  29.  
  30.  
  31.    Pine is in part based on The Elm Mail System:
  32.     ***********************************************************************
  33.     *  The Elm Mail System  -  Revision: 2.13                             *
  34.     *                                                                     *
  35.     *             Copyright (c) 1986, 1987 Dave Taylor              *
  36.     *             Copyright (c) 1988, 1989 USENET Community Trust   *
  37.     ***********************************************************************
  38.  
  39.  
  40.   ----------------------------------------------------------------------*/
  41.  
  42. /*======================================================================
  43.        ttyout.c
  44.        Routines for painting the screen
  45.           - figure out what the terminal type is
  46.           - deal with screen size changes
  47.           - save special output sequences
  48.           - the usual screen clearing, cursor addressing and scrolling
  49.  
  50.  
  51.      This library gives programs the ability to easily access the
  52.      termcap information and write screen oriented and raw input
  53.      programs.  The routines can be called as needed, except that
  54.      to use the cursor / screen routines there must be a call to
  55.      InitScreen() first.  The 'Raw' input routine can be used
  56.      independently, however. (Elm comment)
  57.  
  58.      Not sure what the original source of this code was. It got to be
  59.      here as part of ELM. It has been changed significantly from the
  60.      ELM version to be more robust in the face of inconsistent terminal
  61.      autowrap behaviour. Also, the unused functions were removed, it was
  62.      made to pay attention to the window size, and some code was made nicer
  63.      (in my opinion anyways). It also outputs the terminal initialization
  64.      strings and provides for minimal scrolling and detects terminals
  65.      with out enough capabilities. (Pine comment, 1990)
  66.  
  67.  
  68. This code used to pay attention to the "am" auto margin and "xn"
  69. new line glitch fields, but they were so often incorrect because many
  70. terminals can be configured to do either that we've taken it out. It
  71. now assumes it dosn't know where the cursor is after outputing in the
  72. 80th column.
  73. */
  74.  
  75. #ifdef OS2
  76. #define INCL_BASE
  77. #define INCL_VIO
  78. #define INCL_DOS
  79. #define INCL_NOPM
  80. #include <os2.h>
  81. #undef ADDRESS
  82. #endif
  83.  
  84. #include "headers.h"
  85.  
  86. #define FARAWAY 1000
  87. #define    PUTLINE_BUFLEN    256
  88.  
  89. static int   _lines, _columns;
  90. static int   _line  = FARAWAY;
  91. static int   _col   = FARAWAY;
  92. static int   _in_inverse;
  93.  
  94.  
  95. #if    !(defined(DOS) ||defined(OS2))
  96. /* Beginning of giant ifdef to switch between UNIX and DOS */
  97.  
  98. #ifdef HAVE_TERMIOS
  99. #include <termios.h>
  100. #else
  101. #ifdef HAVE_TERMIO
  102. #include <termio.h>
  103. #else
  104. #include <sgtty.h>
  105. #endif
  106. #endif
  107.  
  108. #ifdef _
  109. #include <sys/tty.h>
  110. #endif
  111.  
  112.  
  113. /*
  114.  * Internal prototypes
  115.  */
  116. static void moveabsolute PROTO((int, int));
  117. static void CursorUp PROTO((int));
  118. static void CursorDown PROTO((int));
  119. static void CursorLeft PROTO((int));
  120. static void CursorRight PROTO((int));
  121.  
  122.  
  123. static char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
  124.             *_setinverse, *_clearinverse,
  125.             *_setunderline, *_clearunderline,
  126.             *_setbold,     *_clearbold,
  127.             *_cleartoeoln, *_cleartoeos,
  128.             *_startinsert, *_endinsert, *_insertchar, *_deletechar,
  129.             *_deleteline, *_insertline,
  130.             *_scrollregion, *_scrollup, *_scrolldown,
  131.             *_termcap_init, *_termcap_end;
  132. char  term_name[40];
  133. #ifndef USE_TERMINFO
  134. static char  _terminal[1024];         /* Storage for terminal entry */
  135. static char  _capabilities[1024];     /* String for cursor motion */
  136. static char *ptr = _capabilities;     /* for buffering         */
  137.  
  138. char  *tgetstr();                    /* Get termcap capability */
  139.  
  140. #endif
  141.  
  142. static enum  {NoScroll,UseScrollRegion,InsertDelete} _scrollmode;
  143.  
  144. char  *tgoto();                /* and the goto stuff    */
  145.  
  146.  
  147.  
  148. /*----------------------------------------------------------------------
  149.       Initialize the screen for output, set terminal type, etc
  150.  
  151.    Args: tt -- Pointer to variable to store the tty output structure.
  152.  
  153.  Result:  terminal size is discovered and set pine state
  154.           termcap entry is fetched and stored in local variables
  155.           make sure terminal has adequate capabilites
  156.           evaluate scrolling situation
  157.           returns status of indicating the state of the screen/termcap entry
  158.  
  159.       Returns:
  160.         -1 indicating no terminal name associated with this shell,
  161.         -2..-n  No termcap for this terminal type known
  162.     -3 Can't open termcap file 
  163.         -4 Terminal not powerful enough - missing clear to eoln or screen
  164.                                            or cursor motion
  165.  
  166.   ----*/
  167. int
  168. config_screen(tt, kbesc)
  169.      struct ttyo **tt;
  170.      KBESC_T     **kbesc;
  171. {
  172.     struct ttyo *ttyo;
  173.     char *getenv();
  174.     char *_ku, *_kd, *_kl, *_kr,
  175.      *_kppu, *_kppd, *_kphome, *_kpend, *_kpdel,
  176.      *_kf1, *_kf2, *_kf3, *_kf4, *_kf5, *_kf6,
  177.      *_kf7, *_kf8, *_kf9, *_kf10, *_kf11, *_kf12;
  178.  
  179. #ifdef USE_TERMINFO
  180.     int setupterm();
  181.     char *tigetstr();
  182.     char *ttnm;
  183.     int err;
  184.  
  185.     *tt = NULL;
  186.     ttnm = getenv ("TERM");
  187.     if (!ttnm) return -1;
  188.     strcpy (term_name, ttnm);
  189.     setupterm (term_name, 1 /* (ignored) */, &err);
  190.     switch (err) {
  191.     case -1 : return -3;
  192.     case 0 : return -2;
  193.     }
  194.  
  195.     ttyo = (struct ttyo *)fs_get(sizeof (struct ttyo));
  196.  
  197.     _line  =  0;        /* where are we right now?? */
  198.     _col   =  0;        /* assume zero, zero...     */
  199.  
  200.     /* load in all those pesky values */
  201.     _clearscreen       = tigetstr("clear");
  202.     _moveto            = tigetstr("cup");
  203.     _up                = tigetstr("cuu1");
  204.     _down              = tigetstr("cud1");
  205.     _right             = tigetstr("cuf1");
  206.     _left              = tigetstr("cub1");
  207.     _setinverse        = tigetstr("smso");
  208.     _clearinverse      = tigetstr("rmso");
  209.     _setunderline      = tigetstr("smul");
  210.     _clearunderline    = tigetstr("rmul");
  211.     _setbold           = tigetstr("bold");
  212.     _clearbold         = tigetstr("sgr0");
  213.     _cleartoeoln       = tigetstr("el");
  214.     _cleartoeos        = tigetstr("ed");
  215.     _deletechar        = tigetstr("dch1");
  216.     _insertchar        = tigetstr("ich1");
  217.     _startinsert       = tigetstr("smir");
  218.     _endinsert         = tigetstr("rmir");
  219.     _deleteline        = tigetstr("dl1");
  220.     _insertline        = tigetstr("il1");
  221.     _scrollregion      = tigetstr("csr");
  222.     _scrolldown        = tigetstr("ind");
  223.     _scrollup          = tigetstr("ri");
  224.     _termcap_init      = tigetstr("smcup");
  225.     _termcap_end       = tigetstr("rmcup");
  226.     _lines           = tigetnum("lines");
  227.     _columns           = tigetnum("cols");
  228.     _ku                = tigetstr("kcuu1");
  229.     _kd                = tigetstr("kcud1");
  230.     _kl                = tigetstr("kcub1");
  231.     _kr                = tigetstr("kcuf1");
  232.     _kppu              = tigetstr("kpp");
  233.     _kppd              = tigetstr("knp");
  234.     _kphome            = tigetstr("khome");
  235.     _kpend             = tigetstr("kend");
  236.     _kpdel             = tigetstr("kdch1");
  237.     _kf1               = tigetstr("kf1");
  238.     _kf2               = tigetstr("kf2");
  239.     _kf3               = tigetstr("kf3");
  240.     _kf4               = tigetstr("kf4");
  241.     _kf5               = tigetstr("kf5");
  242.     _kf6               = tigetstr("kf6");
  243.     _kf7               = tigetstr("kf7");
  244.     _kf8               = tigetstr("kf8");
  245.     _kf9               = tigetstr("kf9");
  246.     _kf10              = tigetstr("kf10");
  247.     _kf11              = tigetstr("kf11");
  248.     _kf12              = tigetstr("kf12");
  249. #else
  250.     char *ttnm;            /* tty name */
  251.     int   tgetent(),        /* get termcap entry */
  252.           err;
  253.  
  254.     *tt = NULL;
  255.     if (!(ttnm = getenv("TERM")) || !strcpy(term_name, ttnm))
  256.       return(-1);
  257.  
  258.     if ((err = tgetent(_terminal, term_name)) != 1)
  259.         return(err-2);
  260.  
  261.     ttyo = (struct ttyo *)fs_get(sizeof (struct ttyo));
  262.  
  263.     _line  =  0;        /* where are we right now?? */
  264.     _col   =  0;        /* assume zero, zero...     */
  265.  
  266.     /* load in all those pesky values */
  267.     ptr                = _capabilities;
  268.     _clearscreen       = tgetstr("cl", &ptr);
  269.     _moveto            = tgetstr("cm", &ptr);
  270.     _up                = tgetstr("up", &ptr);
  271.     _down              = tgetstr("do", &ptr);
  272.     _right             = tgetstr("nd", &ptr);
  273.     _left              = tgetstr("bs", &ptr);
  274.     _setinverse        = tgetstr("so", &ptr);
  275.     _clearinverse      = tgetstr("se", &ptr);
  276.     _setunderline      = tgetstr("us", &ptr);
  277.     _clearunderline    = tgetstr("ue", &ptr);
  278.     _setbold           = tgetstr("md", &ptr);
  279.     _clearbold         = tgetstr("me", &ptr);
  280.     _cleartoeoln       = tgetstr("ce", &ptr);
  281.     _cleartoeos        = tgetstr("cd", &ptr);
  282.     _deletechar        = tgetstr("dc", &ptr);
  283.     _insertchar        = tgetstr("ic", &ptr);
  284.     _startinsert       = tgetstr("im", &ptr);
  285.     _endinsert         = tgetstr("ei", &ptr);
  286.     _deleteline        = tgetstr("dl", &ptr);
  287.     _insertline        = tgetstr("al", &ptr);
  288.     _scrollregion      = tgetstr("cs", &ptr);
  289.     _scrolldown        = tgetstr("sf", &ptr);
  290.     _scrollup          = tgetstr("sr", &ptr);
  291.     _termcap_init      = tgetstr("ti", &ptr);
  292.     _termcap_end       = tgetstr("te", &ptr);
  293.     _lines           = tgetnum("li");
  294.     _columns           = tgetnum("co");
  295.     _ku                = tgetstr("ku", &ptr);
  296.     _kd                = tgetstr("kd", &ptr);
  297.     _kl                = tgetstr("kl", &ptr);
  298.     _kr                = tgetstr("kr", &ptr);
  299.     _kppu              = tgetstr("kP", &ptr);
  300.     _kppd              = tgetstr("kN", &ptr);
  301.     _kphome            = tgetstr("kh", &ptr);
  302.     _kpend             = tgetstr("kE", &ptr);
  303.     _kpdel             = tgetstr("kD", &ptr);
  304.     _kf1               = tgetstr("k1", &ptr);
  305.     _kf2               = tgetstr("k2", &ptr);
  306.     _kf3               = tgetstr("k3", &ptr);
  307.     _kf4               = tgetstr("k4", &ptr);
  308.     _kf5               = tgetstr("k5", &ptr);
  309.     _kf6               = tgetstr("k6", &ptr);
  310.     _kf7               = tgetstr("k7", &ptr);
  311.     _kf8               = tgetstr("k8", &ptr);
  312.     _kf9               = tgetstr("k9", &ptr);
  313.     if((_kf10          = tgetstr("k;", &ptr)) == NULL)
  314.       _kf10            = tgetstr("k0", &ptr);
  315.     _kf11              = tgetstr("F1", &ptr);
  316.     _kf12              = tgetstr("F2", &ptr);
  317. #endif
  318.  
  319.     if(_lines == -1) {
  320.     char *el;
  321.     int   ll;
  322.  
  323.         /* tgetnum failed, try $LINES */
  324.     el = getenv("LINES");
  325.     if(el && (ll = atoi(el)) > 0)
  326.       _lines = ll;
  327.     else
  328.           _lines = DEFAULT_LINES_ON_TERMINAL;
  329.     }
  330.     if(_columns == -1) {
  331.     char *ec;
  332.     int   cc;
  333.  
  334.         /* tgetnum failed, try $COLUMNS */
  335.     ec = getenv("COLUMNS");
  336.     if(ec && (cc = atoi(ec)) > 0)
  337.           _columns = cc;
  338.     else
  339.           _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  340.     }
  341.  
  342.     get_windsize(ttyo);
  343.  
  344.     ttyo->header_rows = 2;
  345.     ttyo->footer_rows = 3;
  346.  
  347.     /*---- Make sure this terminal has the capability.
  348.         All we need is cursor address, clear line, and 
  349.         reverse video.
  350.       ---*/
  351.     if(_moveto == NULL || _cleartoeoln == NULL ||
  352.        _setinverse == NULL || _clearinverse == NULL) {
  353.           return(-4);
  354.     }
  355.  
  356.     dprint(1, (debugfile, "Terminal type: %s\n", term_name));
  357.  
  358.     /*------ Figure out scrolling mode -----*/
  359.     if(_scrollregion != NULL && _scrollregion[0] != '\0' &&
  360.           _scrollup != NULL && _scrollup[0] != '\0'){
  361.         _scrollmode = UseScrollRegion;
  362.     } else if(_insertline != NULL && _insertline[0] != '\0' &&
  363.        _deleteline != NULL && _deleteline[0] != '\0') {
  364.         _scrollmode = InsertDelete;
  365.     } else {
  366.         _scrollmode = NoScroll;
  367.     }
  368.     dprint(7, (debugfile, "Scroll mode: %s\n",
  369.                _scrollmode==NoScroll ? "No Scroll" :
  370.                _scrollmode==InsertDelete ? "InsertDelete" : "Scroll Regions"));
  371.  
  372.  
  373.     if (!_left) {
  374.         _left = "\b";
  375.     }
  376.  
  377.     *tt = ttyo;
  378.  
  379. #ifndef TERMCAP_WINS
  380.     /*
  381.      * Add default keypad sequences to the trie.
  382.      * Since these come first, they will override any conflicting termcap
  383.      * or terminfo escape sequences defined below.  An escape sequence is
  384.      * considered conflicting if one is a prefix of the other.
  385.      * So, without TERMCAP_WINS, there will likely be some termcap/terminfo
  386.      * escape sequences that don't work, because they conflict with default
  387.      * sequences defined here.
  388.      */
  389.     setup_dflt_esc_seq(kbesc);
  390. #endif /* !TERMCAP_WINS */
  391.  
  392.     /*
  393.      * add termcap/info escape sequences to the trie...
  394.      */
  395.  
  396.     if(_ku != NULL && _kd != NULL && _kl != NULL && _kr != NULL){
  397.     kpinsert(kbesc, _ku, KEY_UP);
  398.     kpinsert(kbesc, _kd, KEY_DOWN);
  399.     kpinsert(kbesc, _kl, KEY_LEFT);
  400.     kpinsert(kbesc, _kr, KEY_RIGHT);
  401.     }
  402.  
  403.     if(_kppu != NULL && _kppd != NULL){
  404.     kpinsert(kbesc, _kppu, KEY_PGUP);
  405.     kpinsert(kbesc, _kppd, KEY_PGDN);
  406.     }
  407.  
  408.     kpinsert(kbesc, _kphome, KEY_HOME);
  409.     kpinsert(kbesc, _kpend,  KEY_END);
  410.     kpinsert(kbesc, _kpdel,  KEY_DEL);
  411.  
  412.     kpinsert(kbesc, _kf1,  PF1);
  413.     kpinsert(kbesc, _kf2,  PF2);
  414.     kpinsert(kbesc, _kf3,  PF3);
  415.     kpinsert(kbesc, _kf4,  PF4);
  416.     kpinsert(kbesc, _kf5,  PF5);
  417.     kpinsert(kbesc, _kf6,  PF6);
  418.     kpinsert(kbesc, _kf7,  PF7);
  419.     kpinsert(kbesc, _kf8,  PF8);
  420.     kpinsert(kbesc, _kf9,  PF9);
  421.     kpinsert(kbesc, _kf10, PF10);
  422.     kpinsert(kbesc, _kf11, PF11);
  423.     kpinsert(kbesc, _kf12, PF12);
  424.  
  425. #ifdef TERMCAP_WINS
  426.     /*
  427.      * Add default keypad sequences to the trie.
  428.      * Since these come after the termcap/terminfo escape sequences above,
  429.      * the termcap/info sequences will override any conflicting default
  430.      * escape sequences defined here.
  431.      * So, with TERMCAP_WINS, some of the default sequences will be missing.
  432.      * This means that you'd better get all of your termcap/terminfo entries
  433.      * correct if you define TERMCAP_WINS.
  434.      */
  435.     setup_dflt_esc_seq(kbesc);
  436. #endif /* TERMCAP_WINS */
  437.  
  438.     return(0);
  439. }
  440.  
  441.  
  442.  
  443. /*----------------------------------------------------------------------
  444.    Initialize the screen with the termcap string 
  445.   ----*/
  446. void
  447. init_screen()
  448. {
  449.     if(_termcap_init != NULL) {
  450.     /* init using termcap's rule */
  451.         tputs(_termcap_init, 1, outchar);
  452.     /* and make sure there are no scrolling surprises! */
  453.     BeginScroll(0, ps_global->ttyo->screen_rows);
  454.     /* and make sure icon text starts out consistent */
  455.     icon_text(NULL);
  456.     fflush(stdout);
  457.     }
  458. }
  459.         
  460.  
  461.  
  462.  
  463. /*----------------------------------------------------------------------
  464.        Get the current window size
  465.   
  466.    Args: ttyo -- pointer to structure to store window size in
  467.  
  468.   NOTE: we don't override the given values unless we know better
  469.  ----*/
  470. int
  471. get_windsize(ttyo)
  472. struct ttyo *ttyo;     
  473. {
  474. #ifdef RESIZING 
  475.     struct winsize win;
  476.  
  477.     /*
  478.      * Get the window size from the tty driver.  If we can't fish it from
  479.      * stdout (pine's output is directed someplace else), try stdin (which
  480.      * *must* be associated with the terminal; see init_tty_driver)...
  481.      */
  482.     if(ioctl(1, TIOCGWINSZ, &win) >= 0            /* 1 is stdout */
  483.     || ioctl(0, TIOCGWINSZ, &win) >= 0){        /* 0 is stdin */
  484.     if(win.ws_row)
  485.       _lines = min(win.ws_row, MAX_SCREEN_ROWS);
  486.  
  487.     if(win.ws_col)
  488.       _columns  = min(win.ws_col, MAX_SCREEN_COLS);
  489.  
  490.         dprint(2, (debugfile, "new win size -----<%d %d>------\n",
  491.                    _lines, _columns));
  492.     }
  493.     else
  494.       /* Depending on the OS, the ioctl() may have failed because
  495.      of a 0 rows, 0 columns setting.  That happens on DYNIX/ptx 1.3
  496.      (with a kernel patch that happens to involve the negotiation
  497.      of window size in the telnet streams module.)  In this case
  498.      the error is EINVARG.  Leave the default settings. */
  499.       dprint(1, (debugfile, "ioctl(TIOCWINSZ) failed :%s\n",
  500.          error_description(errno)));
  501. #endif
  502.  
  503.     ttyo->screen_cols = min(_columns, MAX_SCREEN_COLS);
  504.     ttyo->screen_rows = min(_lines, MAX_SCREEN_ROWS);
  505.     return(0);
  506. }
  507.  
  508.  
  509. /*----------------------------------------------------------------------
  510.       End use of the screen.
  511.       Print status message, if any.
  512.       Flush status messages.
  513.   ----*/
  514. void
  515. end_screen(message)
  516.     char *message;
  517. {
  518.     int footer_rows_was_one = 0;
  519.  
  520.     dprint(9, (debugfile, "end_screen called\n"));
  521.  
  522.     if(FOOTER_ROWS(ps_global) == 1){
  523.     footer_rows_was_one++;
  524.     FOOTER_ROWS(ps_global) = 3;
  525.     mark_status_unknown();
  526.     }
  527.  
  528.     flush_status_messages(1);
  529.     blank_keymenu(_lines - 2, 0);
  530.     MoveCursor(_lines - 2, 0);
  531.     if(_termcap_end != NULL)
  532.       tputs(_termcap_end, 1, outchar);
  533.  
  534.     if(message){
  535.     StartInverse();
  536.     printf("%s\r\n", message);
  537.     EndInverse();
  538.     }
  539.  
  540.     fflush(stdout);
  541.  
  542.     if(footer_rows_was_one){
  543.     FOOTER_ROWS(ps_global) = 1;
  544.     mark_status_unknown();
  545.     }
  546. }
  547.     
  548.  
  549.  
  550. /*----------------------------------------------------------------------
  551.      Clear the terminal screen
  552.  
  553.  Result: The screen is cleared
  554.          internal cursor position set to 0,0
  555.   ----*/
  556. void
  557. ClearScreen()
  558. {
  559.     _line = 0;    /* clear leaves us at top... */
  560.     _col  = 0;
  561.  
  562.     if(ps_global->in_init_seq)
  563.       return;
  564.  
  565.     mark_status_unknown();
  566.     mark_keymenu_dirty();
  567.     mark_titlebar_dirty();
  568.  
  569.     if(!_clearscreen){
  570.     ClearLines(0, _lines-1);
  571.         MoveCursor(0, 0);
  572.     }
  573.     else{
  574.     tputs(_clearscreen, 1, outchar);
  575.         moveabsolute(0, 0);  /* some clearscreens don't move correctly */
  576.     }
  577. }
  578.  
  579.  
  580. /*----------------------------------------------------------------------
  581.             Internal move cursor to absolute position
  582.  
  583.   Args: col -- column to move cursor to
  584.         row -- row to move cursor to
  585.  
  586.  Result: cursor is moved (variables, not updates)
  587.   ----*/
  588.  
  589. static void
  590. moveabsolute(col, row)
  591. {
  592.  
  593.     char *stuff, *tgoto();
  594.  
  595.     stuff = tgoto(_moveto, col, row);
  596.     tputs(stuff, 1, outchar);
  597. }
  598.  
  599.  
  600. /*----------------------------------------------------------------------
  601.         Move the cursor to the row and column number
  602.   Args:  row number
  603.          column number
  604.  
  605.  Result: Cursor moves
  606.          internal position updated
  607.   ----*/
  608. void
  609. MoveCursor(row, col)
  610.      int row, col;
  611. {
  612.     /** move cursor to the specified row column on the screen.
  613.         0,0 is the top left! **/
  614.  
  615.     int scrollafter = 0;
  616.  
  617.     /* we don't want to change "rows" or we'll mangle scrolling... */
  618.  
  619.     if(ps_global->in_init_seq)
  620.       return;
  621.  
  622.     if (col < 0)
  623.       col = 0;
  624.     if (col >= ps_global->ttyo->screen_cols)
  625.       col = ps_global->ttyo->screen_cols - 1;
  626.     if (row < 0)
  627.       row = 0;
  628.     if (row > ps_global->ttyo->screen_rows) {
  629.       if (col == 0)
  630.         scrollafter = row - ps_global->ttyo->screen_rows;
  631.       row = ps_global->ttyo->screen_rows;
  632.     }
  633.  
  634.     if (!_moveto)
  635.         return;
  636.  
  637.     if (row == _line) {
  638.       if (col == _col)
  639.         return;                /* already there! */
  640.  
  641.       else if (abs(col - _col) < 5) {    /* within 5 spaces... */
  642.         if (col > _col && _right)
  643.           CursorRight(col - _col);
  644.         else if (col < _col &&  _left)
  645.           CursorLeft(_col - col);
  646.         else
  647.           moveabsolute(col, row);
  648.       }
  649.       else         /* move along to the new x,y loc */
  650.         moveabsolute(col, row);
  651.     }
  652.     else if (col == _col && abs(row - _line) < 5) {
  653.       if (row < _line && _up)
  654.         CursorUp(_line - row);
  655.       else if (_line > row && _down)
  656.         CursorDown(row - _line);
  657.       else
  658.         moveabsolute(col, row);
  659.     }
  660.     else if (_line == row-1 && col == 0) {
  661.       putchar('\n');    /* that's */
  662.       putchar('\r');    /*  easy! */
  663.     }
  664.     else 
  665.       moveabsolute(col, row);
  666.  
  667.     _line = row;    /* to ensure we're really there... */
  668.     _col  = col;
  669.  
  670.     if (scrollafter) {
  671.       while (scrollafter--) {
  672.         putchar('\n');
  673.         putchar('\r');
  674.  
  675.       }
  676.     }
  677.  
  678.     return;
  679. }
  680.  
  681.  
  682.  
  683. /*----------------------------------------------------------------------
  684.          Newline, move the cursor to the start of next line
  685.  
  686.  Result: Cursor moves
  687.   ----*/
  688. void
  689. NewLine()
  690. {
  691.    /** move the cursor to the beginning of the next line **/
  692.  
  693.     Writechar('\n', 0);
  694.     Writechar('\r', 0);
  695. }
  696.  
  697.  
  698.  
  699. /*----------------------------------------------------------------------
  700.         Move cursor up n lines with terminal escape sequence
  701.  
  702.    Args:  n -- number of lines to go up
  703.  
  704.  Result: cursor moves, 
  705.          internal position updated
  706.  
  707.  Only for ttyout use; not outside callers
  708.   ----*/
  709. static void
  710. CursorUp(n)
  711. int n;
  712. {
  713.     /** move the cursor up 'n' lines **/
  714.     /** Calling function must check that _up is not null before calling **/
  715.  
  716.     _line = (_line-n > 0? _line - n: 0);    /* up 'n' lines... */
  717.  
  718.     while (n-- > 0)
  719.       tputs(_up, 1, outchar);
  720. }
  721.  
  722.  
  723.  
  724. /*----------------------------------------------------------------------
  725.         Move cursor down n lines with terminal escape sequence
  726.  
  727.     Arg: n -- number of lines to go down
  728.  
  729.  Result: cursor moves, 
  730.          internal position updated
  731.  
  732.  Only for ttyout use; not outside callers
  733.   ----*/
  734. static void
  735. CursorDown(n)
  736.      int          n;
  737. {
  738.     /** move the cursor down 'n' lines **/
  739.     /** Caller must check that _down is not null before calling **/
  740.  
  741.     _line = (_line+n < ps_global->ttyo->screen_rows ? _line + n
  742.              : ps_global->ttyo->screen_rows);
  743.                                                /* down 'n' lines... */
  744.  
  745.     while (n-- > 0)
  746.         tputs(_down, 1, outchar);
  747. }
  748.  
  749.  
  750.  
  751. /*----------------------------------------------------------------------
  752.         Move cursor left n lines with terminal escape sequence
  753.  
  754.    Args:  n -- number of lines to go left
  755.  
  756.  Result: cursor moves, 
  757.          internal position updated
  758.  
  759.  Only for ttyout use; not outside callers
  760.   ----*/
  761. static void 
  762. CursorLeft(n)
  763. int n;
  764. {
  765.     /** move the cursor 'n' characters to the left **/
  766.     /** Caller must check that _left is not null before calling **/
  767.  
  768.     _col = (_col - n> 0? _col - n: 0);    /* left 'n' chars... */
  769.  
  770.     while (n-- > 0)
  771.       tputs(_left, 1, outchar);
  772. }
  773.  
  774.  
  775. /*----------------------------------------------------------------------
  776.         Move cursor right n lines with terminal escape sequence
  777.  
  778.    Args:  number of lines to go right
  779.  
  780.  Result: cursor moves, 
  781.          internal position updated
  782.  
  783.  Only for ttyout use; not outside callers
  784.   ----*/
  785. static void 
  786. CursorRight(n)
  787. int n;
  788. {
  789.     /** move the cursor 'n' characters to the right (nondestructive) **/
  790.     /** Caller must check that _right is not null before calling **/
  791.  
  792.     _col = (_col+n < ps_global->ttyo->screen_cols? _col + n :
  793.              ps_global->ttyo->screen_cols);    /* right 'n' chars... */
  794.  
  795.     while (n-- > 0)
  796.       tputs(_right, 1, outchar);
  797.  
  798. }
  799.  
  800.  
  801.  
  802. /*----------------------------------------------------------------------
  803.        Start painting inverse on the screen
  804.  
  805.  Result: escape sequence to go into inverse is output
  806.          returns 1 if it was done, 0 if not.
  807.   ----*/
  808. int
  809. StartInverse()
  810. {
  811.     /** set inverse video mode **/
  812.  
  813.     if (!_setinverse)
  814.         return(0);
  815.     
  816.     if(_in_inverse)
  817.       return(1);
  818.  
  819.     _in_inverse = 1;
  820.     tputs(_setinverse, 1, outchar);
  821.     return(1);
  822. }
  823.  
  824.  
  825.  
  826. /*----------------------------------------------------------------------
  827.       End painting inverse on the screen
  828.  
  829.  Result: escape sequence to go out of inverse is output
  830.          returns 1 if it was done, 0 if not.
  831.   ----------------------------------------------------------------------*/
  832. void
  833. EndInverse()
  834. {
  835.     /** compliment of startinverse **/
  836.  
  837.     if (!_clearinverse)
  838.         return;
  839.  
  840.     if(_in_inverse){
  841.     _in_inverse = 0;
  842.     tputs(_clearinverse, 1, outchar);
  843.     }
  844. }
  845.  
  846.  
  847. int
  848. StartUnderline()
  849. {
  850.     if (!_setunderline)
  851.         return(0);
  852.  
  853.     tputs(_setunderline, 1, outchar);
  854.     return(1);
  855. }
  856.  
  857.  
  858. void
  859. EndUnderline()
  860. {
  861.     if (!_clearunderline)
  862.         return;
  863.  
  864.     tputs(_clearunderline, 1, outchar);
  865. }
  866.  
  867. int
  868. StartBold()
  869. {
  870.     if (!_setbold)
  871.         return(0);
  872.  
  873.     tputs(_setbold, 1, outchar);
  874.     return(1);
  875. }
  876.  
  877. void
  878. EndBold()
  879. {
  880.     if (!_clearbold)
  881.         return;
  882.  
  883.     tputs(_clearbold, 1, outchar);
  884. }
  885.  
  886.  
  887.  
  888. /*----------------------------------------------------------------------
  889.        Insert character on screen pushing others right
  890.  
  891.    Args: c --  character to insert
  892.  
  893.  Result: charcter is inserted if possible
  894.          return -1 if it can't be done
  895.   ----------------------------------------------------------------------*/
  896. InsertChar(c)
  897.      int c;
  898. {
  899.     if(_insertchar != NULL && *_insertchar != '\0') {
  900.     tputs(_insertchar, 1, outchar);
  901.     Writechar(c, 0);
  902.     } else if(_startinsert != NULL && *_startinsert != '\0') {
  903.     tputs(_startinsert, 1, outchar);
  904.     Writechar(c, 0);
  905.     tputs(_endinsert, 1, outchar);
  906.     } else {
  907.     return(-1);
  908.     }
  909.     return(0);
  910. }
  911.  
  912.  
  913.  
  914. /*----------------------------------------------------------------------
  915.          Delete n characters from line, sliding rest of line left
  916.  
  917.    Args: n -- number of characters to delete
  918.  
  919.  
  920.  Result: characters deleted on screen
  921.          returns -1 if it wasn't done
  922.   ----------------------------------------------------------------------*/
  923. DeleteChar(n)
  924.      int n;
  925. {
  926.     if(_deletechar == NULL || *_deletechar == '\0')
  927.       return(-1);
  928.  
  929.     while(n) {
  930.     tputs(_deletechar, 1, outchar);
  931.     n--;
  932.     }
  933.     return(0);
  934. }
  935.  
  936.  
  937.  
  938. /*----------------------------------------------------------------------
  939.   Go into scrolling mode, that is set scrolling region if applicable
  940.  
  941.    Args: top    -- top line of region to scroll
  942.          bottom -- bottom line of region to scroll
  943.  
  944.  Result: either set scrolling region or
  945.          save values for later scrolling
  946.          returns -1 if we can't scroll
  947.  
  948.  Unfortunately this seems to leave the cursor in an unpredictable place
  949.  at least the manuals don't say where, so we force it here.
  950. -----*/
  951. static int __t, __b;
  952.  
  953. BeginScroll(top, bottom)
  954.      int top, bottom;
  955. {
  956.     char *stuff;
  957.  
  958.     if(_scrollmode == NoScroll)
  959.       return(-1);
  960.  
  961.     __t = top;
  962.     __b = bottom;
  963.     if(_scrollmode == UseScrollRegion){
  964.         stuff = tgoto(_scrollregion, bottom, top);
  965.         tputs(stuff, 1, outchar);
  966.         /*-- a location  very far away to force a cursor address --*/
  967.         _line = FARAWAY;
  968.         _col  = FARAWAY;
  969.     }
  970.     return(0);
  971. }
  972.  
  973.  
  974.  
  975. /*----------------------------------------------------------------------
  976.    End scrolling -- clear scrolling regions if necessary
  977.  
  978.  Result: Clear scrolling region on terminal
  979.   -----*/
  980. void
  981. EndScroll()
  982. {
  983.     if(_scrollmode == UseScrollRegion && _scrollregion != NULL){
  984.     /* Use tgoto even though we're not cursor addressing because
  985.            the format of the capability is the same.
  986.          */
  987.         char *stuff = tgoto(_scrollregion, ps_global->ttyo->screen_rows -1, 0);
  988.     tputs(stuff, 1, outchar);
  989.         /*-- a location  very far away to force a cursor address --*/
  990.         _line = FARAWAY;
  991.         _col  = FARAWAY;
  992.     }
  993. }
  994.  
  995.  
  996. /* ----------------------------------------------------------------------
  997.     Scroll the screen using insert/delete or scrolling regions
  998.  
  999.    Args:  lines -- number of lines to scroll, positive forward
  1000.  
  1001.  Result: Screen scrolls
  1002.          returns 0 if scroll succesful, -1 if not
  1003.  
  1004.  positive lines goes foward (new lines come in at bottom
  1005.  Leaves cursor at the place to insert put new text
  1006.  
  1007.  0,0 is the upper left
  1008.  -----*/
  1009. ScrollRegion(lines)
  1010.     int lines;
  1011. {
  1012.     int l;
  1013.  
  1014.     if(lines == 0)
  1015.       return(0);
  1016.  
  1017.     if(_scrollmode == UseScrollRegion) {
  1018.     if(lines > 0) {
  1019.         MoveCursor(__b, 0);
  1020.         for(l = lines ; l > 0 ; l--)
  1021.           tputs((_scrolldown == NULL || _scrolldown[0] =='\0') ? "\n" :
  1022.             _scrolldown, 1, outchar);
  1023.     } else {
  1024.         MoveCursor(__t, 0);
  1025.         for(l = -lines; l > 0; l--)
  1026.           tputs(_scrollup, 1, outchar);
  1027.     }
  1028.     } else if(_scrollmode == InsertDelete) {
  1029.     if(lines > 0) {
  1030.         MoveCursor(__t, 0);
  1031.         for(l = lines; l > 0; l--) 
  1032.           tputs(_deleteline, 1, outchar);
  1033.         MoveCursor(__b, 0);
  1034.         for(l = lines; l > 0; l--) 
  1035.           tputs(_insertline, 1, outchar);
  1036.     } else {
  1037.         for(l = -lines; l > 0; l--) {
  1038.             MoveCursor(__b, 0);
  1039.             tputs(_deleteline, 1, outchar);
  1040.         MoveCursor(__t, 0);
  1041.         tputs(_insertline, 1, outchar);
  1042.         }
  1043.     }
  1044.     } else {
  1045.     return(-1);
  1046.     }
  1047.     fflush(stdout);
  1048.     return(0);
  1049. }
  1050.  
  1051.  
  1052.  
  1053. /*----------------------------------------------------------------------
  1054.     Write a character to the screen, keeping track of cursor position
  1055.  
  1056.    Args: ch -- character to output
  1057.  
  1058.  Result: character output
  1059.          cursor position variables updated
  1060.   ----*/
  1061. Writechar(ch, new_esc_len)
  1062.      register unsigned int ch;
  1063.      int      new_esc_len;
  1064. {
  1065.     register int nt;
  1066.     static   int esc_len = 0;
  1067.  
  1068.     if(ps_global->in_init_seq                /* silent */
  1069.        || (F_ON(F_BLANK_KEYMENU, ps_global)        /* or bottom, */
  1070.        && !esc_len                    /* right cell */
  1071.        && _line + 1 == ps_global->ttyo->screen_rows
  1072.        && _col + 1 == ps_global->ttyo->screen_cols))
  1073.       return;
  1074.  
  1075.     if(!iscntrl(ch & 0x7f)){
  1076.     putchar(ch);
  1077.     if(esc_len > 0)
  1078.       esc_len--;
  1079.     else
  1080.       _col++;
  1081.     }
  1082.     else{
  1083.     switch(ch){
  1084.       case LINE_FEED:
  1085.         /*-- Don't have to watch out for auto wrap or newline glitch
  1086.           because we never let it happen. See below
  1087.           ---*/
  1088.         putchar('\n');
  1089.         _line = min(_line+1,ps_global->ttyo->screen_rows);
  1090.         esc_len = 0;
  1091.         break;
  1092.  
  1093.       case RETURN :        /* move to column 0 */
  1094.         putchar('\r');
  1095.         _col = 0;
  1096.         esc_len = 0;
  1097.         break;
  1098.  
  1099.       case BACKSPACE :    /* move back a space if not in column 0 */
  1100.         if(_col != 0) {
  1101.         putchar('\b');
  1102.         _col--;
  1103.         }            /* else BACKSPACE does nothing */
  1104.  
  1105.         break;
  1106.  
  1107.       case BELL :        /* ring the bell but don't advance _col */
  1108.         putchar(ch);
  1109.         break;
  1110.  
  1111.       case TAB :        /* if a tab, output it */
  1112.         do            /* BUG? ignores tty driver's spacing */
  1113.           putchar(' ');
  1114.         while(_col < ps_global->ttyo->screen_cols - 1
  1115.           && ((++_col)&0x07) != 0);
  1116.         break;
  1117.  
  1118.       case ESCAPE :
  1119.         /* If we're outputting an escape here, it may be part of an iso2022
  1120.            escape sequence in which case take up no space on the screen.
  1121.            Unfortunately such sequences are variable in length.
  1122.            */
  1123.         esc_len = new_esc_len - 1;
  1124.         putchar(ch);
  1125.         break;
  1126.  
  1127.       default :        /* Change remaining control characters to ? */
  1128.         putchar('?');
  1129.         if(esc_len > 0)
  1130.           esc_len--;
  1131.         else
  1132.           _col++;
  1133.  
  1134.         break;
  1135.     }
  1136.     }
  1137.  
  1138.  
  1139.     /* Here we are at the end of the line. We've decided to make no
  1140.        assumptions about how the terminal behaves at this point.
  1141.        What can happen now are the following
  1142.            1. Cursor is at start of next line, and next character will
  1143.               apear there. (autowrap, !newline glitch)
  1144.            2. Cursor is at start of next line, and if a newline is output
  1145.               it'll be ignored. (autowrap, newline glitch)
  1146.            3. Cursor is still at end of line and next char will apear
  1147.               there over the top of what is there now (no autowrap).
  1148.        We ignore all this and force the cursor to the next line, just 
  1149.        like case 1. A little expensive but worth it to avoid problems
  1150.        with terminals configured so they don't match termcap
  1151.        */
  1152.     if(_col == ps_global->ttyo->screen_cols) {
  1153.         _col = 0;
  1154.         if(_line + 1 < ps_global->ttyo->screen_rows)
  1155.       _line++;
  1156.  
  1157.     moveabsolute(_col, _line);
  1158.     }
  1159.  
  1160.     return(0);
  1161. }
  1162.  
  1163.  
  1164.  
  1165. /*----------------------------------------------------------------------
  1166.        Write string to screen at current cursor position
  1167.  
  1168.    Args: string -- strings to be output
  1169.  
  1170.  Result: Line written to the screen
  1171.   ----*/
  1172. void
  1173. Write_to_screen(string)                /* UNIX */
  1174.       register char *string; 
  1175. {
  1176.     while(*string)
  1177.       Writechar((unsigned char) *string++, 0);
  1178. }
  1179.  
  1180.  
  1181.  
  1182. /*----------------------------------------------------------------------
  1183.     Clear screen to end of line on current line
  1184.  
  1185.  Result: Line is cleared
  1186.   ----*/
  1187. void
  1188. CleartoEOLN()
  1189. {
  1190.     if(!_cleartoeoln)
  1191.       return;
  1192.  
  1193.     tputs(_cleartoeoln, 1, outchar);
  1194. }
  1195.  
  1196.  
  1197.  
  1198. /*----------------------------------------------------------------------
  1199.      Clear screen to end of screen from current point
  1200.  
  1201.  Result: screen is cleared
  1202.   ----*/
  1203. CleartoEOS()
  1204. {
  1205.     if(!_cleartoeos){
  1206.         CleartoEOLN();
  1207.     ClearLines(_line, _lines-1);
  1208.     }
  1209.     else
  1210.       tputs(_cleartoeos, 1, outchar);
  1211. }
  1212.  
  1213.  
  1214.  
  1215. /*----------------------------------------------------------------------
  1216.      function to output character used by termcap
  1217.  
  1218.    Args: c -- character to output
  1219.  
  1220.  Result: character output to screen via stdio
  1221.   ----*/
  1222. void
  1223. outchar(c)
  1224. int c;
  1225. {
  1226.     /** output the given character.  From tputs... **/
  1227.     /** Note: this CANNOT be a macro!              **/
  1228.  
  1229.     putc(c, stdout);
  1230. }
  1231.  
  1232.  
  1233.  
  1234. /*----------------------------------------------------------------------
  1235.      function to output string such that it becomes icon text
  1236.  
  1237.    Args: s -- string to write
  1238.  
  1239.  Result: string indicated become our "icon" text
  1240.   ----*/
  1241. void
  1242. icon_text(s)
  1243.     char *s;
  1244. {
  1245.     if(F_ON(F_ENABLE_XTERM_NEWMAIL, ps_global) && getenv("DISPLAY")){
  1246.     fputs("\033]1;", stdout);
  1247.     fputs((s) ? s : ps_global->pine_name, stdout);
  1248.     fputs("\007", stdout);
  1249.     fflush(stdout);
  1250.     }
  1251. }
  1252.  
  1253.  
  1254.  
  1255. #else /* DOS && OS2 */  /* Middle of giant ifdef for DOS & OS2 drivers */
  1256.  
  1257.  
  1258. /*----------------------------------------------------------------------
  1259.       Initialize the screen for output, set terminal type, etc
  1260.  
  1261.  Input: TERM and TERMCAP environment variables
  1262.         Pointer to variable to store the tty output structure.
  1263.  
  1264.  Result:  terminal size is discovered and set pine state
  1265.           termcap entry is fetched and stored in local variables
  1266.           make sure terminal has adequate capabilites
  1267.           evaluate scrolling situation
  1268.           returns status of indicating the state of the screen/termcap entry
  1269.   ----------------------------------------------------------------------*/
  1270. void
  1271. init_screen()                    /* DOS */
  1272. {
  1273.     return;                    /* NO OP */
  1274. }
  1275.  
  1276.  
  1277.  
  1278. /*----------------------------------------------------------------------
  1279.       End use of the screen. 
  1280.   ----------------------------------------------------------------------*/
  1281. void
  1282. end_screen(message)                /* DOS */
  1283.     char *message;
  1284. {
  1285.     extern void exit_text_mode();
  1286.     int footer_rows_was_one = 0;
  1287.  
  1288.     if(FOOTER_ROWS(ps_global) == 1){
  1289.     footer_rows_was_one++;
  1290.     FOOTER_ROWS(ps_global) = 3;
  1291.     mark_status_unknown();
  1292.     }
  1293.  
  1294.     flush_status_messages(1);
  1295.  
  1296.     blank_keymenu(_lines - 2, 0);
  1297.  
  1298.     if(message){
  1299.     StartInverse();
  1300.     PutLine0(_lines - 2, 0, message);
  1301.     }
  1302.     
  1303.     EndInverse();
  1304.  
  1305.     MoveCursor(_lines - 1, 0);
  1306. #ifndef _WINDOWS
  1307.     exit_text_mode(NULL);
  1308. #endif
  1309.     ibmclose();
  1310.     if(footer_rows_was_one){
  1311.     FOOTER_ROWS(ps_global) = 1;
  1312.     mark_status_unknown();
  1313.     }
  1314. }
  1315.  
  1316. #ifdef OS2
  1317. static void
  1318. get_dimen(int *width, int *length)
  1319. {
  1320.     VIOMODEINFO vm;
  1321.     vm.cb = sizeof vm;
  1322.     VioGetMode(&vm, 0);
  1323.     *width = vm.col;
  1324.     *length = vm.row;
  1325. }
  1326. #endif
  1327.  
  1328.  
  1329. /*----------------------------------------------------------------------
  1330.       Initialize the screen for output, set terminal type, etc
  1331.  
  1332.    Args: tt -- Pointer to variable to store the tty output structure.
  1333.  
  1334.  Result:  terminal size is discovered and set pine state
  1335.           termcap entry is fetched and stored in local variables
  1336.           make sure terminal has adequate capabilites
  1337.           evaluate scrolling situation
  1338.           returns status of indicating the state of the screen/termcap entry
  1339.  
  1340.       Returns:
  1341.         -1 indicating no terminal name associated with this shell,
  1342.         -2..-n  No termcap for this terminal type known
  1343.     -3 Can't open termcap file 
  1344.         -4 Terminal not powerful enough - missing clear to eoln or screen
  1345.                                            or cursor motion
  1346.  
  1347.   ----*/
  1348. int
  1349. config_screen(tt, kbesc)            /* DOS */
  1350.      struct ttyo **tt;
  1351.      KBESC_T     **kbesc;
  1352. {
  1353.     struct ttyo *ttyo;
  1354. #ifndef _WINDOWS
  1355.     extern void enter_text_mode();
  1356. #endif
  1357.  
  1358.     _line  =  0;        /* where are we right now?? */
  1359.     _col   =  0;        /* assume zero, zero...     */
  1360.  
  1361. #ifdef _WINDOWS
  1362.     mswin_getscreensize(&_lines, &_columns);
  1363.     if (_lines > MAX_SCREEN_ROWS)
  1364.     _lines = MAX_SCREEN_ROWS;
  1365.     if (_columns > MAX_SCREEN_COLS)
  1366.     _columns = MAX_SCREEN_COLS;
  1367. #else
  1368. #ifdef OS2
  1369.     get_dimen(&_columns, &_lines);
  1370. #else
  1371.     _lines   = DEFAULT_LINES_ON_TERMINAL;
  1372.     _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  1373. #endif
  1374. #endif
  1375.     ttyo = (struct ttyo *)fs_get(sizeof(struct ttyo));
  1376.     ttyo->screen_cols = _columns;
  1377.     ttyo->screen_rows = _lines ;
  1378.     ttyo->header_rows = 2;
  1379.     ttyo->footer_rows = 3;
  1380.  
  1381. #ifndef _WINDOWS
  1382.     enter_text_mode(NULL);
  1383. #endif
  1384.     ibmopen();
  1385.  
  1386.     *tt = ttyo;
  1387.  
  1388.     return(0);
  1389. }
  1390.  
  1391.  
  1392.     
  1393. /*----------------------------------------------------------------------
  1394.        Get the current window size
  1395.   
  1396.    Args: ttyo -- pointer to structure to store window size in
  1397.  
  1398.   NOTE: we don't override the given values unless we know better
  1399.  ----*/
  1400. int
  1401. get_windsize(ttyo)                /* DOS */
  1402. struct ttyo *ttyo;     
  1403. {
  1404. #ifdef _WINDOWS
  1405.     char    fontName[LF_FACESIZE+1];
  1406.     char    fontSize[12];
  1407.     char    fontStyle[64];
  1408.     char    windowPosition[32];
  1409.     int        newRows, newCols;
  1410.     
  1411.         
  1412.     /* Get the new window parameters and update the 'pinerc' variables. */
  1413.     mswin_getwindow (fontName, fontSize, fontStyle, windowPosition);
  1414.     if(!ps_global->VAR_FONT_NAME
  1415.        || strucmp(ps_global->VAR_FONT_NAME, fontName))
  1416.       set_variable(V_FONT_NAME, fontName, 0);
  1417.  
  1418.     if(!ps_global->VAR_FONT_SIZE
  1419.        || strucmp(ps_global->VAR_FONT_SIZE, fontSize))
  1420.       set_variable(V_FONT_SIZE, fontSize, 0);
  1421.  
  1422.     if(!ps_global->VAR_FONT_STYLE
  1423.        || strucmp(ps_global->VAR_FONT_STYLE, fontStyle))
  1424.       set_variable(V_FONT_STYLE, fontStyle, 0);
  1425.  
  1426.     if(!ps_global->VAR_WINDOW_POSITION
  1427.        || strucmp(ps_global->VAR_WINDOW_POSITION, windowPosition))
  1428.       set_variable(V_WINDOW_POSITION, windowPosition, 0);
  1429.  
  1430.     mswin_getprintfont (fontName, fontSize, fontStyle);
  1431.     if(!ps_global->VAR_PRINT_FONT_NAME
  1432.        || strucmp(ps_global->VAR_PRINT_FONT_NAME, fontName))
  1433.       set_variable(V_PRINT_FONT_NAME, fontName, 0);
  1434.  
  1435.     if(!ps_global->VAR_PRINT_FONT_SIZE
  1436.        || strucmp(ps_global->VAR_PRINT_FONT_SIZE, fontSize))
  1437.       set_variable(V_PRINT_FONT_SIZE, fontSize, 0);
  1438.  
  1439.     if(!ps_global->VAR_PRINT_FONT_STYLE
  1440.        || strucmp(ps_global->VAR_PRINT_FONT_STYLE, fontStyle))
  1441.       set_variable(V_PRINT_FONT_STYLE, fontStyle, 0);
  1442.  
  1443.     /* Get new window size.  Compare to old.  The window may have just
  1444.      * moved, in which case we don't bother updating the size. */
  1445.     mswin_getscreensize(&newRows, &newCols);
  1446.     if (newRows == ttyo->screen_rows && newCols == ttyo->screen_cols)
  1447.         return (NO_OP_COMMAND);
  1448.  
  1449.     /* True resize. */
  1450.     ttyo->screen_rows = newRows;
  1451.     ttyo->screen_cols = newCols;
  1452.  
  1453.     if (ttyo->screen_rows > MAX_SCREEN_ROWS)
  1454.     ttyo->screen_rows = MAX_SCREEN_ROWS;
  1455.     if (ttyo->screen_cols > MAX_SCREEN_COLS)
  1456.     ttyo->screen_cols = MAX_SCREEN_COLS;
  1457.  
  1458.     return(KEY_RESIZE);
  1459. #else
  1460. #ifdef OS2
  1461.     get_dimen(&_columns, &_lines);
  1462. #else
  1463.     ttyo->screen_cols = _columns;
  1464.     ttyo->screen_rows = _lines;
  1465. #endif
  1466.     return(0);
  1467. #endif
  1468. }
  1469.     
  1470.  
  1471.  
  1472.  
  1473. /*----------------------------------------------------------------------
  1474.      Clear the terminal screen
  1475.  
  1476.  Input:  none
  1477.  
  1478.  Result: The screen is cleared
  1479.          internal cursor position set to 0,0
  1480.   ----------------------------------------------------------------------*/
  1481. void
  1482. ClearScreen()                    /* DOS */
  1483. {
  1484.     _line = 0;            /* clear leaves us at top... */
  1485.     _col  = 0;
  1486.  
  1487.     if(ps_global->in_init_seq)
  1488.       return;
  1489.  
  1490.     mark_status_unknown();
  1491.     mark_keymenu_dirty();
  1492.     mark_titlebar_dirty();
  1493.  
  1494.     ibmmove(0, 0);
  1495.     ibmeeop();
  1496. }
  1497.  
  1498.  
  1499.  
  1500. /*----------------------------------------------------------------------
  1501.         Move the cursor to the row and column number
  1502.  Input:  row number
  1503.          column number
  1504.  
  1505.  Result: Cursor moves
  1506.          internal position updated
  1507.   ----------------------------------------------------------------------*/
  1508. void
  1509. MoveCursor(row, col)                /* DOS */
  1510.      int row, col;
  1511. {
  1512.     /** move cursor to the specified row column on the screen.
  1513.         0,0 is the top left! **/
  1514.  
  1515.     if(ps_global->in_init_seq)
  1516.       return;
  1517.  
  1518.     ibmmove(row, col);
  1519.     _line = row;
  1520.     _col = col;
  1521. }
  1522.  
  1523.  
  1524.  
  1525. /*----------------------------------------------------------------------
  1526.          Newline, move the cursor to the start of next line
  1527.  
  1528.  Input:  none
  1529.  
  1530.  Result: Cursor moves
  1531.   ----------------------------------------------------------------------*/
  1532. void
  1533. NewLine()                    /* DOS */
  1534. {
  1535.     /** move the cursor to the beginning of the next line **/
  1536.  
  1537.     MoveCursor(_line+1, 0);
  1538. }
  1539.  
  1540.  
  1541.  
  1542.  
  1543. /*----------------------------------------------------------------------
  1544.        Start painting inverse on the screen
  1545.  
  1546.  Input:  none
  1547.  
  1548.  Result: escape sequence to go into inverse is output
  1549.          returns 1 if it was done, 0 if not.
  1550.   ----------------------------------------------------------------------*/
  1551. int
  1552. StartInverse()                    /* DOS */
  1553. {
  1554.     if(_in_inverse)
  1555.       return(1);
  1556.  
  1557.     _in_inverse = 1;
  1558.     ibmrev(1);                    /* libpico call */
  1559.     return(1);
  1560. }
  1561.  
  1562.  
  1563. /*----------------------------------------------------------------------
  1564.       End painting inverse on the screen
  1565.  
  1566.  Input:  none
  1567.  
  1568.  Result: escape sequence to go out of inverse is output
  1569.          returns 1 if it was done, 0 if not.
  1570.   ----------------------------------------------------------------------*/
  1571. void
  1572. EndInverse()                    /* DOS */
  1573. {
  1574.     if(_in_inverse){
  1575.     _in_inverse = 0;
  1576.     ibmrev(0);                /* libpico call */
  1577.     }
  1578. }
  1579.  
  1580.  
  1581. /*
  1582.  * Character attriute stuff that could use some work
  1583.  * MS 92.05.18
  1584.  */
  1585.  
  1586. int
  1587. StartUnderline()                /* DOS */
  1588. {
  1589.     return(0);
  1590. }
  1591.  
  1592. void                        /* DOS */
  1593. EndUnderline()
  1594. {
  1595. }
  1596.  
  1597. int
  1598. StartBold()                    /* DOS */
  1599. {
  1600.     return(0);
  1601. }
  1602.  
  1603. void
  1604. EndBold()                    /* DOS */
  1605. {
  1606. }
  1607.  
  1608.  
  1609. /*----------------------------------------------------------------------
  1610.        Insert character on screen pushing others right
  1611.  
  1612.  Input:  character to output
  1613.          termcap escape sequences
  1614.  
  1615.  Result: charcter is inserted if possible
  1616.          return -1 if it can't be done
  1617.   ----------------------------------------------------------------------*/
  1618. InsertChar(c)                    /* DOS */
  1619.      int c;
  1620. {
  1621. #ifdef _WINDOWS
  1622.     mswin_inschar (c);
  1623.     return (0);
  1624. #else
  1625.     return(-1);
  1626. #endif
  1627. }
  1628.  
  1629.  
  1630. /*----------------------------------------------------------------------
  1631.          Delete n characters from line, sliding rest of line left
  1632.  
  1633.  Input:  number of characters to delete
  1634.          termcap escape sequences
  1635.  
  1636.  Result: characters deleted on screen
  1637.          returns -1 if it wasn't done
  1638.   ----------------------------------------------------------------------*/
  1639. DeleteChar(n)                    /* DOS */
  1640.      int n;
  1641. {
  1642.     char c;
  1643.     int oc;                /* original column */
  1644.  
  1645. #ifdef _WINDOWS
  1646.     mswin_delchar ();
  1647. #else
  1648.     oc = _col;
  1649. /* cursor OFF */
  1650.     while(_col < 79){
  1651.     ibmmove(_line, _col+1);
  1652.         readscrn(&c);
  1653.     ibmmove(_line, _col++);
  1654.     ibmputc(c);
  1655.     }
  1656.     ibmputc(' ');
  1657.     ibmmove(_line, oc);
  1658. /* cursor ON */
  1659. #endif
  1660. }
  1661.  
  1662.  
  1663.  
  1664. /*----------------------------------------------------------------------
  1665.   Go into scrolling mode, that is set scrolling region if applicable
  1666.  
  1667.  Input: top line of region to scroll
  1668.         bottom line of region to scroll
  1669.  
  1670.  Result: either set scrolling region or
  1671.          save values for later scrolling
  1672.          returns -1 if we can't scroll
  1673.  
  1674.  Unfortunately this seems to leave the cursor in an unpredictable place
  1675.  at least the manuals don't say were, so we force it here.
  1676. ----------------------------------------------------------------------*/
  1677. static int __t, __b;
  1678. BeginScroll(top, bottom)            /* DOS */
  1679.      int top, bottom;
  1680. {
  1681.     __t = top;
  1682.     __b = bottom;
  1683. }
  1684.  
  1685. /*----------------------------------------------------------------------
  1686.    End scrolling -- clear scrolling regions if necessary
  1687.  
  1688.  Input:  none
  1689.  
  1690.  Result: Clear scrolling region on terminal
  1691.   ----------------------------------------------------------------------*/
  1692. void
  1693. EndScroll()                    /* DOS */
  1694. {
  1695. }
  1696.  
  1697.  
  1698. /* ----------------------------------------------------------------------
  1699.     Scroll the screen using insert/delete or scrolling regions
  1700.  
  1701.  Input:  number of lines to scroll, positive forward
  1702.  
  1703.  Result: Screen scrolls
  1704.          returns 0 if scroll succesful, -1 if not
  1705.  
  1706.  positive lines goes foward (new lines come in at bottom
  1707.  Leaves cursor at the place to insert put new text
  1708.  
  1709.  0,0 is the upper left
  1710.  ----------------------------------------------------------------------*/
  1711. ScrollRegion(lines)                /* DOS */
  1712.     int lines;
  1713. {
  1714.     return(-1);
  1715. }
  1716.  
  1717.  
  1718. /*----------------------------------------------------------------------
  1719.     Write a character to the screen, keeping track of cursor position
  1720.  
  1721.  Input:  charater to write
  1722.  
  1723.  Result: character output
  1724.          cursor position variables updated
  1725.   ----------------------------------------------------------------------*/
  1726. Writechar(ch, new_esc_len)                /* DOS */
  1727.      register unsigned int ch;
  1728.      int      new_esc_len;
  1729. {
  1730.     register int nt;
  1731.  
  1732.     if(ps_global->in_init_seq)
  1733.       return(0);
  1734.  
  1735.     switch(ch){
  1736.       case LINE_FEED :
  1737.     _line = min(_line+1,ps_global->ttyo->screen_rows);
  1738.         _col =0;
  1739.         ibmmove(_line, _col);
  1740.     break;
  1741.  
  1742.       case RETURN :        /* move to column 0 */
  1743.     _col = 0;
  1744.         ibmmove(_line, _col);
  1745.  
  1746.       case BACKSPACE :        /* move back a space if not in column 0 */
  1747.     if(_col > 0)
  1748.           ibmmove(_line, --_col);
  1749.  
  1750.     break;
  1751.     
  1752.       case BELL :        /* ring the bell but don't advance _col */
  1753.     ibmbeep();        /* libpico call */
  1754.     break;
  1755.  
  1756.       case TAB:            /* if a tab, output it */
  1757.     do
  1758.       ibmputc(' ');
  1759.     while(((++_col)&0x07) != 0);
  1760.     break;
  1761.  
  1762.       default:
  1763.     /*if some kind of control or  non ascii character change to a '?'*/
  1764.     if(iscntrl(ch & 0x7f))
  1765.       ch = '?';
  1766.  
  1767.     ibmputc(ch);
  1768.     _col++;
  1769.     }
  1770.  
  1771.     if(_col == ps_global->ttyo->screen_cols) {
  1772.       _col  = 0;
  1773.       if(_line + 1 < ps_global->ttyo->screen_rows)
  1774.         _line++;
  1775.  
  1776.       ibmmove(_line, _col);
  1777.     }
  1778.  
  1779.     return(0);
  1780. }
  1781.  
  1782.  
  1783. /*----------------------------------------------------------------------
  1784.       Printf style write directly to the terminal at current position
  1785.  
  1786.  Input: printf style control string
  1787.         number of printf style arguments
  1788.         up to three printf style arguments
  1789.  
  1790.  Result: Line written to the screen
  1791.   ----------------------------------------------------------------------*/
  1792. void
  1793. Write_to_screen(string)                /* DOS */
  1794.       register char *string;
  1795. {
  1796.     if(ps_global->in_init_seq)
  1797.       return;
  1798.  
  1799. #ifdef _WINDOWS
  1800.     mswin_puts (string);
  1801. #else
  1802.     while(*string)
  1803.       Writechar(*string++, 0);
  1804. #endif
  1805. }
  1806.  
  1807.  
  1808.  
  1809. /*----------------------------------------------------------------------
  1810.     Clear screen to end of line on current line
  1811.  
  1812.  Input:  none
  1813.  
  1814.  Result: Line is cleared
  1815.   ----------------------------------------------------------------------*/
  1816. void
  1817. CleartoEOLN()                    /* DOS */
  1818. {
  1819.     ibmeeol();                    /* libpico call */
  1820. }
  1821.  
  1822.  
  1823. /*----------------------------------------------------------------------
  1824.           Clear screen to end of screen from current point
  1825.  
  1826.  Input: none
  1827.  
  1828.  Result: screen is cleared
  1829.   ----------------------------------------------------------------------*/
  1830. CleartoEOS()                    /* DOS */
  1831. {
  1832.     ibmeeop();
  1833. }
  1834.  
  1835.  
  1836. /*----------------------------------------------------------------------
  1837.      function to output string such that it becomes icon text
  1838.  
  1839.    Args: s -- string to write
  1840.  
  1841.  Result: string indicated become our "icon" text
  1842.   ----*/
  1843. void
  1844. icon_text(s)                    /* DOS */
  1845.     char *s;
  1846. {
  1847.     return;                    /* NO OP */
  1848. }
  1849.  
  1850.  
  1851. #ifndef    _WINDOWS
  1852. /*
  1853.  * readscrn - DOS magic to read the character on the display at the
  1854.  *            current cursor position
  1855.  */
  1856. readscrn(c)                    /* DOS */
  1857. char *c;
  1858. {
  1859.     ibmgetc(c);
  1860. }
  1861. #endif    /* !_WINDOWS */
  1862. #endif    /* DOS -- End of giant ifdef for DOS drivers */
  1863.  
  1864.  
  1865. /*
  1866.  * Generic tty output routines...
  1867.  */
  1868.  
  1869. /*----------------------------------------------------------------------
  1870.       Printf style output line to the screen at given position, 0 args
  1871.  
  1872.   Args:  x -- column position on the screen
  1873.          y -- row position on the screen
  1874.          line -- line of text to output
  1875.  
  1876.  Result: text is output
  1877.          cursor position is update
  1878.   ----*/
  1879. void
  1880. PutLine0(x, y, line)
  1881.     int            x,y;
  1882.     register char *line;
  1883. {
  1884.     MoveCursor(x,y);
  1885.     Write_to_screen(line);
  1886. }
  1887.  
  1888.  
  1889.  
  1890. /*----------------------------------------------------------------------
  1891.   Output line of length len to the display observing embedded attributes
  1892.  
  1893.  Args:  x      -- column position on the screen
  1894.         y      -- column position on the screen
  1895.         line   -- text to be output
  1896.         length -- length of text to be output
  1897.  
  1898.  Result: text is output
  1899.          cursor position is updated
  1900.   ----------------------------------------------------------------------*/
  1901. void
  1902. PutLine0n8b(x, y, line, length)
  1903.     int            x, y, length;
  1904.     register char *line;
  1905. {
  1906.     unsigned char c;
  1907.  
  1908.     MoveCursor(x,y);
  1909.     while(length-- && (c = (unsigned char)*line++))
  1910.       if(c == (unsigned char)TAG_EMBED && length){
  1911.       length--;
  1912.       switch(*line++){
  1913.         case TAG_INVON :
  1914.           StartInverse();
  1915.           break;
  1916.         case TAG_INVOFF :
  1917.           EndInverse();
  1918.           break;
  1919.         case TAG_BOLDON :
  1920.           StartBold();
  1921.           break;
  1922.         case TAG_BOLDOFF :
  1923.           EndBold();
  1924.           break;
  1925.         case TAG_ULINEON :
  1926.           StartUnderline();
  1927.           break;
  1928.         case TAG_ULINEOFF :
  1929.           EndUnderline();
  1930.           break;
  1931.         /* default: other embedded vals are handles, just ignore 'em */
  1932.       }                    /* tag with handle, skip it */
  1933.       }    
  1934.       else if(c == '\033')            /* check for iso-2022 escape */
  1935.     Writechar(c, match_escapes(line));
  1936.       else
  1937.     Writechar(c, 0);
  1938. }
  1939.  
  1940.  
  1941. /*----------------------------------------------------------------------
  1942.       Printf style output line to the screen at given position, 1 arg
  1943.  
  1944.  Input:  position on the screen
  1945.          line of text to output
  1946.  
  1947.  Result: text is output
  1948.          cursor position is update
  1949.   ----------------------------------------------------------------------*/
  1950. void
  1951. /*VARARGS2*/
  1952. PutLine1(x, y, line, arg1)
  1953.     int   x, y;
  1954.     char *line;
  1955.     void *arg1;
  1956. {
  1957.     char buffer[PUTLINE_BUFLEN];
  1958.  
  1959.     sprintf(buffer, line, arg1);
  1960.     PutLine0(x, y, buffer);
  1961. }
  1962.  
  1963.  
  1964. /*----------------------------------------------------------------------
  1965.       Printf style output line to the screen at given position, 2 args
  1966.  
  1967.  Input:  position on the screen
  1968.          line of text to output
  1969.  
  1970.  Result: text is output
  1971.          cursor position is update
  1972.   ----------------------------------------------------------------------*/
  1973. void
  1974. /*VARARGS3*/
  1975. PutLine2(x, y, line, arg1, arg2)
  1976.     int   x, y;
  1977.     char *line;
  1978.     void *arg1, *arg2;
  1979. {
  1980.     char buffer[PUTLINE_BUFLEN];
  1981.  
  1982.     sprintf(buffer, line, arg1, arg2);
  1983.     PutLine0(x, y, buffer);
  1984. }
  1985.  
  1986.  
  1987. /*----------------------------------------------------------------------
  1988.       Printf style output line to the screen at given position, 3 args
  1989.  
  1990.  Input:  position on the screen
  1991.          line of text to output
  1992.  
  1993.  Result: text is output
  1994.          cursor position is update
  1995.   ----------------------------------------------------------------------*/
  1996. void
  1997. /*VARARGS4*/
  1998. PutLine3(x, y, line, arg1, arg2, arg3)
  1999.     int   x, y;
  2000.     char *line;
  2001.     void *arg1, *arg2, *arg3;
  2002. {
  2003.     char buffer[PUTLINE_BUFLEN];
  2004.  
  2005.     sprintf(buffer, line, arg1, arg2, arg3);
  2006.     PutLine0(x, y, buffer);
  2007. }
  2008.  
  2009.  
  2010. /*----------------------------------------------------------------------
  2011.       Printf style output line to the screen at given position, 4 args
  2012.  
  2013.  Args:  x -- column position on the screen
  2014.         y -- column position on the screen
  2015.         line -- printf style line of text to output
  2016.  
  2017.  Result: text is output
  2018.          cursor position is update
  2019.   ----------------------------------------------------------------------*/
  2020. void
  2021. /*VARARGS5*/
  2022. PutLine4(x, y, line, arg1, arg2, arg3, arg4)
  2023.      int   x, y;
  2024.      char *line;
  2025.      void *arg1, *arg2, *arg3, *arg4;
  2026. {
  2027.     char buffer[PUTLINE_BUFLEN];
  2028.  
  2029.     sprintf(buffer, line, arg1, arg2, arg3, arg4);
  2030.     PutLine0(x, y, buffer);
  2031. }
  2032.  
  2033.  
  2034.  
  2035. /*----------------------------------------------------------------------
  2036.       Printf style output line to the screen at given position, 5 args
  2037.  
  2038.  Args:  x -- column position on the screen
  2039.         y -- column position on the screen
  2040.         line -- printf style line of text to output
  2041.  
  2042.  Result: text is output
  2043.          cursor position is update
  2044.   ----------------------------------------------------------------------*/
  2045. void
  2046. /*VARARGS6*/
  2047. PutLine5(x, y, line, arg1, arg2, arg3, arg4, arg5)
  2048.      int   x, y;
  2049.      char *line;
  2050.      void *arg1, *arg2, *arg3, *arg4, *arg5;
  2051. {
  2052.     char buffer[PUTLINE_BUFLEN];
  2053.  
  2054.     sprintf(buffer, line, arg1, arg2, arg3, arg4, arg5);
  2055.     PutLine0(x, y, buffer);
  2056. }
  2057.  
  2058.  
  2059.  
  2060. /*----------------------------------------------------------------------
  2061.        Output a line to the screen, centered
  2062.  
  2063.   Input:  Line number to print on, string to output
  2064.   
  2065.  Result:  String is output to screen
  2066.           Returns column number line is output on
  2067.   ----------------------------------------------------------------------*/
  2068. int
  2069. Centerline(line, string)
  2070.     int   line;
  2071.     char *string;
  2072. {
  2073.     register int length, col;
  2074.  
  2075.     length = strlen(string);
  2076.  
  2077.     if (length > ps_global->ttyo->screen_cols)
  2078.       col = 0;
  2079.     else
  2080.       col = (ps_global->ttyo->screen_cols - length) / 2;
  2081.  
  2082.     PutLine0(line, col, string);
  2083.     return(col);
  2084. }
  2085.  
  2086.  
  2087.  
  2088. /*----------------------------------------------------------------------
  2089.      Clear specified line on the screen
  2090.  
  2091.  Result: The line is blanked and the cursor is left at column 0.
  2092.  
  2093.   ----*/
  2094. void
  2095. ClearLine(n)
  2096.     int n;
  2097. {
  2098.     if(ps_global->in_init_seq)
  2099.       return;
  2100.  
  2101.     MoveCursor(n, 0);
  2102.     CleartoEOLN();
  2103. }
  2104.  
  2105.  
  2106.  
  2107. /*----------------------------------------------------------------------
  2108.      Clear specified lines on the screen
  2109.  
  2110.  Result: The lines starting at 'x' and ending at 'y' are blanked
  2111.      and the cursor is left at row 'x', column 0
  2112.  
  2113.   ----*/
  2114. void
  2115. ClearLines(x, y)
  2116.     int x, y;
  2117. {
  2118.     int i;
  2119.  
  2120.     for(i = x; i <= y; i++)
  2121.       ClearLine(i);
  2122.  
  2123.     MoveCursor(x, 0);
  2124. }
  2125.  
  2126.  
  2127.  
  2128. /*----------------------------------------------------------------------
  2129.     Indicate to the screen painting here that the position of the cursor
  2130.  has been disturbed and isn't where these functions might think.
  2131.  ----*/
  2132. void
  2133. clear_cursor_pos()
  2134. {
  2135.     _line = FARAWAY;
  2136.     _col  = FARAWAY;
  2137. }
  2138.  
  2139.  
  2140. /*----------------------------------------------------------------------
  2141.       Return current inverse state
  2142.  
  2143.  Result: returns 1 if in inverse state, 0 if not.
  2144.   ----------------------------------------------------------------------*/
  2145. int
  2146. InverseState()
  2147. {
  2148.     return(_in_inverse);
  2149. }
  2150.